home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-17 | 6.7 KB | 241 lines | [TEXT/KAHL] |
- //******************************************
- // Travelling Salesman by Ronald M. Nepsund
-
- #include <math.h>
-
- #define fracBase 0x20000000
-
- //There are two 32 by 20 arrays of longs
- //which together give the distance betwean
- //any two cities.
- //Instead of using Array[i,j] to access
- //the array Array[(i<<5)+j] is used
- //and two longs are needed to accurately
- //measure the distance betwean cities
- //so two arrays of longs are used.
- //gDistanceFrac is used to hold the
- //fractional part of distance in 1/0x20000000
- //of a unit.
- long gDistanceInt[640],
- gDistanceFrac[640];
- //these are used to represent a path betwean the cities.
- Byte gNextCity[20],gOptPath[20];
- //how long is the currently selected best path so far.
- long gBestPathLength,gFracBestPathLength;
-
- unsigned short gNumCities;
- unsigned short gStartCityIndex;
-
- //precalculated square root for zero to 25
- long qSquTableInt[] =
- {0,1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,
- 4,4,4,4,4,4,4,4,4,
- 5,5,5,5,5,5,5,5,5,5,5};
- //precalculated square root - fractional part
- //in 1/0x20000000 of a whole unit
- long qSquTableFrac[] =
- {0,0,222379212,393016784,0,126738030,
- 241317968,346685095,444758425,0,
- 87122155,169986639,249162657,
- 325102865,398174277,468679365,0,
- 66091829,130266726,192682403,
- 253476060,312767944,370664138,
- 427258795,482635936,0 };
-
- void DoPath(short cityIndex, long InttPathLength, long fracPathLength);
-
- //The recursive routien that actually finds
- //the shortest path.
- void DoPath(register short cityIndex,
- long InttPathLength,
- long fracPathLength)
- {
- register short i;
- Boolean lastCity;
- long offset;
-
- if (fracPathLength > fracBase) {
- //the fractional value variable has
- //exceeded the value of one whole
- //unit
- InttPathLength += 1;
- fracPathLength -= fracBase;
- }
-
- //Has the path has become longer than the
- //shortest path we have already found?
- if (InttPathLength > gBestPathLength ||
- ((InttPathLength == gBestPathLength) &&
- (fracPathLength >= gFracBestPathLength)))
- return;
-
- //lastCity is used to tell if all the
- //cities have been visited
- lastCity = TRUE;
- //for each city
- for(i = 0; i<gNumCities; i++)
- //if not to same city or already
- //visited city
- if ( i != cityIndex &&
- gNextCity[i] == 0xFF) {
- //not at the end of the path
- lastCity = FALSE;
- //path from city 'cityIndex' to 'i'
- gNextCity[cityIndex] = i;
- //offset into distance arrays
- offset = (cityIndex << 5) + i;
- //go to next city adding the
- //distance to that city to the
- //path length
- DoPath(i,
- InttPathLength+gDistanceInt[offset],
- fracPathLength+gDistanceFrac[offset]);
- } //end if and for
-
- // if this is the last city in the chain and
- // is a shorter path than the previous best
- if ((lastCity) &&
- ((InttPathLength < gBestPathLength) ||
- ((InttPathLength == gBestPathLength) &&
- (fracPathLength < gFracBestPathLength))
- ) ) {
- // make this the current best path
- register long *LPnt1,*LPnt2;
- //this is the current shortest path length now
- gBestPathLength = InttPathLength;
- gFracBestPathLength = fracPathLength;
- //copy path to 'optPath'
- LPnt1 = (long *)&gNextCity;
- LPnt2 = (long *)&gOptPath;
- for (i= ((3+gNumCities) >> 2); i>0; i--)
- *LPnt2++ = *LPnt1++;
- } else
- //this city is no longer connected to the next city
- gNextCity[cityIndex] = 0xFF;
- }
-
-
- void InitDistances(unsigned short numCities, Point *citiesPtr);
-
- //initialize two arrays which will give the
- //distance betwean any two cities.
- void InitDistances(
- unsigned short numCities,
- Point *citiesPtr)
- {
- short i,j,offset;
- register long *LPntl1,*LPntF1,
- *LPntI2,*LPntF2;
- long dist;
- short deltax,deltay;
- double X;
-
-
- //The distance from city i to j is the same
- //as from city j to i.
- //Use pointers into the arrays
- //We will add a constant to the pointers to
- //step through the array
- //instead of doing a multiplication to find
- //the wanted entries in the array
-
- //how far is it betwean any two cities
- for (i=0; i<numCities; i++) {
- LPntl1 = gDistanceInt + i;
- LPntF1 = gDistanceFrac + i;
- offset = i << 5;
- LPntI2 = gDistanceInt + offset;
- LPntF2 = gDistanceFrac + offset;
- for (j=0; j<=i; j++)
- if (i==j) {
- //both pointers are pointing
- //to the same locations in the array
- //distance to the same city is zero
- *LPntI2++ = 0;
- *LPntl1 = 0; LPntl1 += 32;
- *LPntF2++;
- LPntF1 += 32;
- } else {
- //calculate horizontal and vertical distance betwean city 'i' and 'j'
- deltax = citiesPtr[i].h-citiesPtr[j].h;
- deltay = citiesPtr[i].v-citiesPtr[j].v;
- //The distance betwean the cities is
- // squareRoot( deltax*deltax + deltay*deltay)
- //Where you can, do multiplications using shorts
- //instead of long's - They are faster.
- if (-255< deltax && deltax<256)
- if (-255< deltay && deltay<256)
- dist = ((long)(deltax*deltax) + (long)(deltay*deltay));
- else
- dist = ((long)(deltax*deltax) + (long)deltay*deltay);
- else
- if (-255< deltay && deltay<256)
- dist = ((long)deltax*deltax + (long)(deltay*deltay));
- else
- dist = ((long)deltax*deltax + (long)deltay*deltay);
-
-
- //do squareRoot
- if (dist <= 25) {
- //use sqrt lookup tables for 0 to 25
- *LPntI2++ = *LPntl1 = qSquTableInt[dist];
- LPntl1 += 32;
- *LPntF2++ = *LPntF1 = qSquTableFrac[dist];
- LPntF1 += 32;
- } else {
- X = sqrt(dist);
- //gDistanceInt[(i << 5) + j] = X;
- //gDistanceInt[(j << 5) + i] = X;
- dist = X; // integer part of distance betwean points
- *LPntl1 = *LPntI2++ = dist;
- LPntl1 += 32;
-
- //gDistanceFrac[i << 5 + j] = (X - dist) * $20000000;
- //gDistanceFrac[j << 5 + i] = (X - dist) * $20000000;
- dist = (X - dist) * fracBase; // fractional part
- *LPntF2++ = *LPntF1 = dist;
- LPntF1 += 32;
- }
- }
- }
- }
-
- void OptimalPath(unsigned short numCities,unsigned short startCityIndex,
- Point *citiesPtr,Point *optimalPathPtr);
-
- void OptimalPath(numCities,startCityIndex,citiesPtr,optimalPathPtr)
- unsigned short numCities;
- unsigned short startCityIndex;
- Point *citiesPtr;
- Point *optimalPathPtr;
- {
- register short i,j;
- long time,index;
- double X;
-
- //generates the tables for the distances betwean any two cities.
- //This routien takes up most of the time.
- InitDistances(numCities,citiesPtr);
-
- //OxFF means that there is no path from
- //this city to another
- for (i=0; i<numCities; i++)
- gNextCity[i] = 0xFF; //no paths betwean cities
-
- gNumCities = numCities;
- gStartCityIndex = startCityIndex;
- //any path done by DoPath will be shorter than this
- gBestPathLength = 0x7FFFFFFF;
- gFracBestPathLength = 0;
-
- DoPath(startCityIndex,0,0); //find the best path
-
- //put the best path into the form
- //desired for 'optimalPath'
- j=startCityIndex;
- for(i=0; i<numCities; i++) {
- optimalPathPtr[i] = citiesPtr[j];
- j = gOptPath[j];
- }
- }
-